/*
 * MainForm.java
 *
 * Created on 28 de agosto de 2007, 11:20 AM
 */
package thermologic.gui;

import java.awt.Dimension;
import java.awt.Toolkit;
import java.awt.event.MouseEvent;
import java.io.File;

import javax.swing.JFileChooser;
import javax.swing.JOptionPane;
import javax.swing.UIManager;

import javax.swing.tree.DefaultMutableTreeNode;
import javax.swing.tree.DefaultTreeModel;
import javax.swing.tree.MutableTreeNode;

import javax.swing.tree.TreePath;
import org.apache.log4j.Logger;
import thermologic.core.Adapter;
import thermologic.core.AdapterEvent;
import thermologic.core.AdapterException;
import thermologic.core.AdapterFactory;
import thermologic.core.AdapterListener;
import thermologic.core.Channel;
import thermologic.core.Datalogger;
import thermologic.core.Device;
import thermologic.core.DeviceSearchThread;
import thermologic.file.FileHandler;
import thermologic.file.DefaultFileHandler;
import thermologic.file.FileFilterImpl;
import thermologic.file.ExcelFileHandler;
import thermologic.file.XMLFileHandler;
import thermologic.onewire.EventCode;

/**
 *
 * @author  inf_mauror
 */
public class MainForm extends javax.swing.JFrame implements AdapterListener {

    private static Logger logger = Logger.getLogger(MainForm.class);
    
    /**
     * Custom components
     */
    private Adapter adapter;    
    
    /**
     * Setup dialog
     */
    private SetupDialog setupDialog;
    
    /**
     * Tree Model for device data
     */
    private DefaultTreeModel deviceModel;
    
    /**
     * Table Model for trace data
     */
    private TraceDataModel traceDataModel;
    
    /**
     * Table model for channel configuration data
     */
    private ConfigurationDataModel configDataModel;
    
    /**    
     * Table Model for samples data
     */
    private SamplesDataModel samplesDataModel;
    
    /**
     * List model for channel selector
     */
    private ChannelListModel channelListModel;
    
    /**
     * root node of device tree
     */
    DefaultMutableTreeNode root;
    
    /**
     * File chooser for saving and opening files
     */
    JFileChooser fileChooser;    
    
    /**
     * File chooser for XML files
     */
    JFileChooser XMLFileChooser;
    
    /**
     * Chart panel
     */
    private MainChart mainChart;    

    /** Creates new form MainForm */
    public MainForm() {
        //setLookAndFeel();
        initModels();
        initComponents();
        initCustomComponents();
        configureWindow();
    }

    public void setLookAndFeel() {
        try {
            UIManager.setLookAndFeel("org.fife.plaf.Office2003.Office2003LookAndFeel");
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    /**
     * Fills the tree with the device array
     * 
     * @param devices device array
     */
    public void populateDeviceTree(Device[] devices) {

        Datalogger datalogger = null;

        if (devices != null && devices.length > 0) {
            if (devices[0] instanceof Datalogger) {
                resetDeviceTree();

                for (Device d : devices) {
                    datalogger = (Datalogger) d;

                    DefaultMutableTreeNode newNode = new DefaultMutableTreeNode(datalogger);
                    deviceModel.insertNodeInto(newNode, root, root.getChildCount());

                    deviceTree.scrollPathToVisible(new TreePath(newNode.getPath()));
                /*
                deviceModel.removeSelectionPath(devicetree.getSelectionPath());
                deviceTree.addSelectionPath(new TreePath(newNode.getPath()));
                 */
                }
            }
        }
    }

    /**
     * Deletes the device tree
     */
    public void resetDeviceTree() {
        int count = deviceModel.getChildCount(root);
        MutableTreeNode nodes[] = new MutableTreeNode[count];

        for (int i = 0; i < count; i++) {
            nodes[i] = (MutableTreeNode) deviceModel.getChild(root, i);
        }

        for (MutableTreeNode node : nodes) {
            deviceModel.removeNodeFromParent(node);
        }

    }

    private void configureWindow() {

        this.setExtendedState(MAXIMIZED_BOTH);

        Toolkit tk = Toolkit.getDefaultToolkit();

        int width = tk.getScreenSize().getSize().width;
        int height = tk.getScreenSize().getSize().height;

        int tmpHeight = (int) (height * 0.25);
        int tmpWidth = (int) (width * 0.25);


        devicePanel.setMinimumSize(
                new Dimension(tmpWidth, tmpHeight));

        splitPane2.setMinimumSize(
                new Dimension(width, tmpHeight));

    /*
     * Poner ventana en Modo de pantalla completa
     * 
    GraphicsDevice graphicsDevice = GraphicsEnvironment.getLocalGraphicsEnvironment().getDefaultScreenDevice();
    graphicsDevice.setFullScreenWindow(this);
     */
    }

    /** This method is called from within the constructor to
     * initialize the form.
     * WARNING: Do NOT modify this code. The content of this method is
     * always regenerated by the Form Editor.
     */
    // <editor-fold defaultstate="collapsed" desc="Generated Code">//GEN-BEGIN:initComponents
    private void initComponents() {

        devicePopupMenu = new javax.swing.JPopupMenu();
        traceMenuItem = new javax.swing.JMenuItem();
        configMenuItem = new javax.swing.JMenuItem();
        samplesMenuItem = new javax.swing.JMenuItem();
        separator2 = new javax.swing.JSeparator();
        setupMenuItem = new javax.swing.JMenuItem();
        statusPanel = new javax.swing.JPanel();
        activityBar = new javax.swing.JProgressBar();
        statusLabel = new javax.swing.JLabel();
        splitPane = new javax.swing.JSplitPane();
        splitPane2 = new javax.swing.JSplitPane();
        devicePanel = new javax.swing.JPanel();
        deviceTree = new javax.swing.JTree();
        TabPane = new javax.swing.JTabbedPane();
        traceTab = new javax.swing.JPanel();
        traceTagsPanelScroll = new javax.swing.JScrollPane();
        tagsTable = new javax.swing.JTable();
        configTab = new javax.swing.JPanel();
        channelCombo1 = new javax.swing.JComboBox();
        jScrollPane1 = new javax.swing.JScrollPane();
        configTable = new javax.swing.JTable();
        dataTab = new javax.swing.JPanel();
        samplesPanelScroll = new javax.swing.JScrollPane();
        samplesTable = new javax.swing.JTable();
        channelCombo2 = new javax.swing.JComboBox();
        menuBar = new javax.swing.JMenuBar();
        fileMenu = new javax.swing.JMenu();
        newMenuItem = new javax.swing.JMenuItem();
        openMenuItem = new javax.swing.JMenuItem();
        saveMenuItem = new javax.swing.JMenuItem();
        menuSeparator3 = new javax.swing.JSeparator();
        exportMenu = new javax.swing.JMenu();
        exportToExcelMenuItem = new javax.swing.JMenuItem();
        exportToXMLMenuItem = new javax.swing.JMenuItem();
        menuSeparator1 = new javax.swing.JSeparator();
        printSetupMenuItem = new javax.swing.JMenuItem();
        printMenuItem = new javax.swing.JMenuItem();
        menuSeparator2 = new javax.swing.JSeparator();
        closeMenuItem = new javax.swing.JMenuItem();
        adapterMenu = new javax.swing.JMenu();
        adapterRead = new javax.swing.JMenuItem();
        setupDeviceMenuItem = new javax.swing.JMenuItem();

        java.util.ResourceBundle bundle = java.util.ResourceBundle.getBundle("properties/language"); // NOI18N
        traceMenuItem.setText(bundle.getString("thermologic.traceTab")); // NOI18N
        traceMenuItem.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                traceMenuItemActionPerformed(evt);
            }
        });
        devicePopupMenu.add(traceMenuItem);

        configMenuItem.setText(bundle.getString("thermologic.configTab")); // NOI18N
        devicePopupMenu.add(configMenuItem);

        samplesMenuItem.setText(bundle.getString("thermologic.dataTab")); // NOI18N
        devicePopupMenu.add(samplesMenuItem);
        devicePopupMenu.add(separator2);

        setupMenuItem.setText(bundle.getString("thermologic.setupdialog.title")); // NOI18N
        setupMenuItem.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                setupMenuItemActionPerformed(evt);
            }
        });
        devicePopupMenu.add(setupMenuItem);

        setDefaultCloseOperation(javax.swing.WindowConstants.EXIT_ON_CLOSE);
        setTitle(bundle.getString("thermologic.title")); // NOI18N
        setExtendedState(MAXIMIZED_BOTH);
        setName("mainWindow"); // NOI18N

        statusPanel.setBorder(javax.swing.BorderFactory.createEtchedBorder(javax.swing.border.EtchedBorder.RAISED));
        statusPanel.setLayout(new java.awt.FlowLayout(java.awt.FlowLayout.LEFT));
        statusPanel.add(activityBar);

        statusLabel.setText(bundle.getString("thermologic.readerStatusLabel")); // NOI18N
        statusPanel.add(statusLabel);

        getContentPane().add(statusPanel, java.awt.BorderLayout.SOUTH);

        splitPane.setDividerLocation(200);
        splitPane.setDividerSize(8);
        splitPane.setOrientation(javax.swing.JSplitPane.VERTICAL_SPLIT);
        splitPane.setOneTouchExpandable(true);

        splitPane2.setDividerLocation(450);
        splitPane2.setDividerSize(8);
        splitPane2.setMinimumSize(new java.awt.Dimension(0, 0));
        splitPane2.setOneTouchExpandable(true);
        splitPane2.setPreferredSize(new java.awt.Dimension(0, 0));

        devicePanel.setMinimumSize(new java.awt.Dimension(350, 300));
        devicePanel.setOpaque(false);
        devicePanel.setPreferredSize(new java.awt.Dimension(0, 0));
        devicePanel.setRequestFocusEnabled(false);
        devicePanel.setLayout(new java.awt.BorderLayout());

        deviceTree.addTreeSelectionListener(new javax.swing.event.TreeSelectionListener() {
            public void valueChanged(javax.swing.event.TreeSelectionEvent evt) {
                deviceTreeValueChanged(evt);
            }
        });
        deviceTree.addMouseListener(new java.awt.event.MouseAdapter() {
            public void mousePressed(java.awt.event.MouseEvent evt) {
                deviceTreeMousePressed(evt);
            }
            public void mouseReleased(java.awt.event.MouseEvent evt) {
                deviceTreeMouseReleased(evt);
            }
        });
        devicePanel.add(deviceTree, java.awt.BorderLayout.CENTER);

        splitPane2.setLeftComponent(devicePanel);

        TabPane.setMinimumSize(new java.awt.Dimension(400, 300));

        traceTagsPanelScroll.setBackground(javax.swing.UIManager.getDefaults().getColor("List.background"));

        tagsTable.setModel(traceDataModel);
        traceTagsPanelScroll.setViewportView(tagsTable);

        org.jdesktop.layout.GroupLayout traceTabLayout = new org.jdesktop.layout.GroupLayout(traceTab);
        traceTab.setLayout(traceTabLayout);
        traceTabLayout.setHorizontalGroup(
            traceTabLayout.createParallelGroup(org.jdesktop.layout.GroupLayout.LEADING)
            .add(traceTabLayout.createSequentialGroup()
                .addContainerGap()
                .add(traceTagsPanelScroll, org.jdesktop.layout.GroupLayout.DEFAULT_SIZE, 422, Short.MAX_VALUE)
                .addContainerGap())
        );
        traceTabLayout.setVerticalGroup(
            traceTabLayout.createParallelGroup(org.jdesktop.layout.GroupLayout.LEADING)
            .add(traceTabLayout.createSequentialGroup()
                .addContainerGap()
                .add(traceTagsPanelScroll, org.jdesktop.layout.GroupLayout.DEFAULT_SIZE, 139, Short.MAX_VALUE)
                .addContainerGap())
        );

        TabPane.addTab(bundle.getString("thermologic.traceTab"), new javax.swing.ImageIcon(getClass().getResource("/icons/trace_icon.png")), traceTab); // NOI18N

        channelCombo1.setModel(channelListModel);
        channelCombo1.addItemListener(new java.awt.event.ItemListener() {
            public void itemStateChanged(java.awt.event.ItemEvent evt) {
                channelCombo1ItemStateChanged(evt);
            }
        });

        configTable.setModel(configDataModel);
        jScrollPane1.setViewportView(configTable);

        org.jdesktop.layout.GroupLayout configTabLayout = new org.jdesktop.layout.GroupLayout(configTab);
        configTab.setLayout(configTabLayout);
        configTabLayout.setHorizontalGroup(
            configTabLayout.createParallelGroup(org.jdesktop.layout.GroupLayout.LEADING)
            .add(configTabLayout.createSequentialGroup()
                .addContainerGap()
                .add(configTabLayout.createParallelGroup(org.jdesktop.layout.GroupLayout.LEADING)
                    .add(jScrollPane1, org.jdesktop.layout.GroupLayout.DEFAULT_SIZE, 422, Short.MAX_VALUE)
                    .add(channelCombo1, org.jdesktop.layout.GroupLayout.PREFERRED_SIZE, org.jdesktop.layout.GroupLayout.DEFAULT_SIZE, org.jdesktop.layout.GroupLayout.PREFERRED_SIZE))
                .addContainerGap())
        );
        configTabLayout.setVerticalGroup(
            configTabLayout.createParallelGroup(org.jdesktop.layout.GroupLayout.LEADING)
            .add(configTabLayout.createSequentialGroup()
                .addContainerGap()
                .add(channelCombo1, org.jdesktop.layout.GroupLayout.PREFERRED_SIZE, 22, org.jdesktop.layout.GroupLayout.PREFERRED_SIZE)
                .addPreferredGap(org.jdesktop.layout.LayoutStyle.RELATED)
                .add(jScrollPane1, org.jdesktop.layout.GroupLayout.DEFAULT_SIZE, 111, Short.MAX_VALUE)
                .addContainerGap())
        );

        TabPane.addTab(bundle.getString("thermologic.configTab"), new javax.swing.ImageIcon(getClass().getResource("/icons/config_icon.png")), configTab); // NOI18N

        samplesTable.setModel(samplesDataModel);
        samplesPanelScroll.setViewportView(samplesTable);

        channelCombo2.setModel(channelListModel);
        channelCombo2.addItemListener(new java.awt.event.ItemListener() {
            public void itemStateChanged(java.awt.event.ItemEvent evt) {
                channelCombo2ItemStateChanged(evt);
            }
        });

        org.jdesktop.layout.GroupLayout dataTabLayout = new org.jdesktop.layout.GroupLayout(dataTab);
        dataTab.setLayout(dataTabLayout);
        dataTabLayout.setHorizontalGroup(
            dataTabLayout.createParallelGroup(org.jdesktop.layout.GroupLayout.LEADING)
            .add(dataTabLayout.createSequentialGroup()
                .addContainerGap()
                .add(dataTabLayout.createParallelGroup(org.jdesktop.layout.GroupLayout.LEADING)
                    .add(samplesPanelScroll, org.jdesktop.layout.GroupLayout.DEFAULT_SIZE, 422, Short.MAX_VALUE)
                    .add(channelCombo2, org.jdesktop.layout.GroupLayout.PREFERRED_SIZE, org.jdesktop.layout.GroupLayout.DEFAULT_SIZE, org.jdesktop.layout.GroupLayout.PREFERRED_SIZE))
                .addContainerGap())
        );
        dataTabLayout.setVerticalGroup(
            dataTabLayout.createParallelGroup(org.jdesktop.layout.GroupLayout.LEADING)
            .add(dataTabLayout.createSequentialGroup()
                .addContainerGap()
                .add(channelCombo2, org.jdesktop.layout.GroupLayout.PREFERRED_SIZE, 22, org.jdesktop.layout.GroupLayout.PREFERRED_SIZE)
                .addPreferredGap(org.jdesktop.layout.LayoutStyle.RELATED)
                .add(samplesPanelScroll, org.jdesktop.layout.GroupLayout.DEFAULT_SIZE, 111, Short.MAX_VALUE)
                .addContainerGap())
        );

        TabPane.addTab(bundle.getString("thermologic.dataTab"), new javax.swing.ImageIcon(getClass().getResource("/icons/data_icon.png")), dataTab); // NOI18N

        splitPane2.setRightComponent(TabPane);

        splitPane.setTopComponent(splitPane2);

        getContentPane().add(splitPane, java.awt.BorderLayout.CENTER);

        fileMenu.setText(bundle.getString("thermologic.menu.file")); // NOI18N

        newMenuItem.setIcon(new javax.swing.ImageIcon(getClass().getResource("/icons/file_new.png"))); // NOI18N
        newMenuItem.setText(bundle.getString("thermologic.menu.fileNew")); // NOI18N
        fileMenu.add(newMenuItem);

        openMenuItem.setIcon(new javax.swing.ImageIcon(getClass().getResource("/icons/file_open.png"))); // NOI18N
        openMenuItem.setText(bundle.getString("thermologic.menu.fileOpen")); // NOI18N
        openMenuItem.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                openMenuItemActionPerformed(evt);
            }
        });
        fileMenu.add(openMenuItem);

        saveMenuItem.setIcon(new javax.swing.ImageIcon(getClass().getResource("/icons/file_save.png"))); // NOI18N
        saveMenuItem.setText(bundle.getString("thermologic.menu.fileSave")); // NOI18N
        saveMenuItem.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                saveMenuItemActionPerformed(evt);
            }
        });
        fileMenu.add(saveMenuItem);
        fileMenu.add(menuSeparator3);

        exportMenu.setText(bundle.getString("thermologic.menu.export")); // NOI18N

        exportToExcelMenuItem.setIcon(new javax.swing.ImageIcon(getClass().getResource("/icons/data_icon.png"))); // NOI18N
        exportToExcelMenuItem.setText(bundle.getString("thermologic.menu.exportToExcel")); // NOI18N
        exportToExcelMenuItem.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                exportToExcelMenuItemActionPerformed(evt);
            }
        });
        exportMenu.add(exportToExcelMenuItem);

        exportToXMLMenuItem.setText(bundle.getString("thermologic.menu.exportToXML")); // NOI18N
        exportToXMLMenuItem.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                exportToXMLMenuItemActionPerformed(evt);
            }
        });
        exportMenu.add(exportToXMLMenuItem);

        fileMenu.add(exportMenu);
        fileMenu.add(menuSeparator1);

        printSetupMenuItem.setIcon(new javax.swing.ImageIcon(getClass().getResource("/icons/file_print_setup.png"))); // NOI18N
        printSetupMenuItem.setText(bundle.getString("thermologic.menu.filePrintSetup")); // NOI18N
        fileMenu.add(printSetupMenuItem);

        printMenuItem.setIcon(new javax.swing.ImageIcon(getClass().getResource("/icons/file_print.png"))); // NOI18N
        printMenuItem.setText(bundle.getString("thermologic.menu.filePrint")); // NOI18N
        fileMenu.add(printMenuItem);
        fileMenu.add(menuSeparator2);

        closeMenuItem.setText(bundle.getString("thermologic.menu.fileClose")); // NOI18N
        closeMenuItem.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                closeMenuItemActionPerformed(evt);
            }
        });
        fileMenu.add(closeMenuItem);

        menuBar.add(fileMenu);

        adapterMenu.setText(bundle.getString("thermologic.menu.adapter")); // NOI18N

        adapterRead.setIcon(new javax.swing.ImageIcon(getClass().getResource("/icons/adapter.png"))); // NOI18N
        adapterRead.setText(bundle.getString("thermologic.menu.captureData")); // NOI18N
        adapterRead.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                adapterReadActionPerformed(evt);
            }
        });
        adapterMenu.add(adapterRead);

        setupDeviceMenuItem.setIcon(new javax.swing.ImageIcon(getClass().getResource("/icons/config_icon.png"))); // NOI18N
        setupDeviceMenuItem.setText(bundle.getString("thermologic.setupdialog.title")); // NOI18N
        setupDeviceMenuItem.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                setupDeviceMenuItemActionPerformed(evt);
            }
        });
        adapterMenu.add(setupDeviceMenuItem);

        menuBar.add(adapterMenu);

        setJMenuBar(menuBar);

        pack();
    }// </editor-fold>//GEN-END:initComponents

private void adapterReadActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_adapterReadActionPerformed

    if (!adapter.isBussy()) {
        Thread thread = new Thread(new DeviceSearchThread(adapter));
        thread.start();
    }
}//GEN-LAST:event_adapterReadActionPerformed

private void openMenuItemActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_openMenuItemActionPerformed

    int retValue = fileChooser.showOpenDialog(this);

    if (retValue == JFileChooser.APPROVE_OPTION) {
        File file = fileChooser.getSelectedFile();
        FileHandler fileHandler = new DefaultFileHandler();

        try {
            Device deviceData[] = (Device[]) fileHandler.load(file);
            populateDeviceTree(deviceData);
        } catch (Exception e) {
            logger.error(e);

            JOptionPane.showMessageDialog(
                    this,
                    e.getLocalizedMessage(),
                    String.format(
                    java.util.ResourceBundle.getBundle("properties/language").getString("thermologic.openfile.error"),
                    file.getName()),
                    JOptionPane.ERROR_MESSAGE);
        }
    }
}//GEN-LAST:event_openMenuItemActionPerformed

    private void channelSelected() {
        /**
         * Clean the samples table, the config data
         * and the chart.
         */
        samplesDataModel.setSamples(null);
        configDataModel.setChannel(null);
        mainChart.clear();

        /**
         * Gets the samples from selected channel and
         * puts them into samples table model
         */
        Channel channelSelected = (Channel) channelListModel.getSelectedItem();
        if (channelSelected != null) {
            configDataModel.setChannel(channelSelected);
            samplesDataModel.setSamples(channelSelected.getSamples());
            mainChart.setUp(channelSelected);
        }

        /**
         * Update the UI component
         */
        samplesTable.updateUI();
        configTable.updateUI();
    }

private void channelCombo2ItemStateChanged(java.awt.event.ItemEvent evt) {//GEN-FIRST:event_channelCombo2ItemStateChanged
    channelSelected();
}//GEN-LAST:event_channelCombo2ItemStateChanged

private void deviceTreeValueChanged(javax.swing.event.TreeSelectionEvent evt) {//GEN-FIRST:event_deviceTreeValueChanged

    DefaultMutableTreeNode node = (DefaultMutableTreeNode) deviceTree.getLastSelectedPathComponent();
    if (node != null) {
        /**
         * Clean the channel list and the 
         * samples table model
         */
        channelListModel.setChannels(null);
        configDataModel.setChannel(null);
        samplesDataModel.setSamples(null);

        /**
         * Set the trace data model
         */
        Datalogger datalogger = (Datalogger) node.getUserObject();
        if(datalogger != null)
        {
            traceDataModel.setDatalogger(datalogger);

            /**
             * Set the channel list model
             */
            channelListModel.setChannels(datalogger.getChannels());

            /**
             * if there is at least one channel the first
             * channel is selected
             */
            if (datalogger.getChannels().length > 0) {
                channelListModel.setSelectedItem(datalogger.getChannels()[0]);
                channelSelected();
            }

            /**
             * Update the UI components
             */
            channelCombo1.updateUI();
            channelCombo2.updateUI();
            tagsTable.updateUI();
            configTable.updateUI();
            samplesTable.updateUI();
        }
    }
}//GEN-LAST:event_deviceTreeValueChanged

private void channelCombo1ItemStateChanged(java.awt.event.ItemEvent evt) {//GEN-FIRST:event_channelCombo1ItemStateChanged
    channelSelected();
}//GEN-LAST:event_channelCombo1ItemStateChanged

private void saveMenuItemActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_saveMenuItemActionPerformed

    FileHandler fileHandler = new DefaultFileHandler();
    FileFilterImpl fileFilter = new FileFilterImpl(FileFilterImpl.EXTENSION);
    
    saveFile(fileHandler, fileFilter);
}//GEN-LAST:event_saveMenuItemActionPerformed

private void exportToExcelMenuItemActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_exportToExcelMenuItemActionPerformed

    FileHandler fileHandler = new ExcelFileHandler();
    FileFilterImpl fileFilter = new FileFilterImpl(FileFilterImpl.EXCEL_EXTENSION);
    
    saveFile(fileHandler, fileFilter);
}//GEN-LAST:event_exportToExcelMenuItemActionPerformed

private void setupDeviceMenuItemActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_setupDeviceMenuItemActionPerformed
   setupDialog.show(SetupStep.STEP1, null);
}//GEN-LAST:event_setupDeviceMenuItemActionPerformed

private void deviceTreeMousePressed(java.awt.event.MouseEvent evt) {//GEN-FIRST:event_deviceTreeMousePressed
   showPopup(evt);
}//GEN-LAST:event_deviceTreeMousePressed

private void deviceTreeMouseReleased(java.awt.event.MouseEvent evt) {//GEN-FIRST:event_deviceTreeMouseReleased
  showPopup(evt);
}//GEN-LAST:event_deviceTreeMouseReleased

private void traceMenuItemActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_traceMenuItemActionPerformed
// TODO add your handling code here:
}//GEN-LAST:event_traceMenuItemActionPerformed

private void setupMenuItemActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_setupMenuItemActionPerformed
  
    DefaultMutableTreeNode node = (DefaultMutableTreeNode)deviceTree.
                    getLastSelectedPathComponent();

    if (node != null)
    {
        Datalogger datalogger = (Datalogger) node.getUserObject();
        if(datalogger != null)
        {
            setupDialog.show(SetupStep.STEP2, datalogger);
        }
    }
}//GEN-LAST:event_setupMenuItemActionPerformed

private void exportToXMLMenuItemActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_exportToXMLMenuItemActionPerformed

    FileHandler fileHandler = new XMLFileHandler();
    FileFilterImpl fileFilter = new FileFilterImpl(FileFilterImpl.XML_EXTENSION);
    
    saveFile(fileHandler, fileFilter);    
}//GEN-LAST:event_exportToXMLMenuItemActionPerformed

private void closeMenuItemActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_closeMenuItemActionPerformed
    dispose();
}//GEN-LAST:event_closeMenuItemActionPerformed

    /**
     * @param args the command line arguments
     */
    public static void main(String args[]) {
        java.awt.EventQueue.invokeLater(new Runnable() {

            public void run() {
                new MainForm().setVisible(true);
            }
        });
    }
    // Variables declaration - do not modify//GEN-BEGIN:variables
    private javax.swing.JTabbedPane TabPane;
    private javax.swing.JProgressBar activityBar;
    private javax.swing.JMenu adapterMenu;
    private javax.swing.JMenuItem adapterRead;
    private javax.swing.JComboBox channelCombo1;
    private javax.swing.JComboBox channelCombo2;
    private javax.swing.JMenuItem closeMenuItem;
    private javax.swing.JMenuItem configMenuItem;
    private javax.swing.JPanel configTab;
    private javax.swing.JTable configTable;
    private javax.swing.JPanel dataTab;
    private javax.swing.JPanel devicePanel;
    private javax.swing.JPopupMenu devicePopupMenu;
    private javax.swing.JTree deviceTree;
    private javax.swing.JMenu exportMenu;
    private javax.swing.JMenuItem exportToExcelMenuItem;
    private javax.swing.JMenuItem exportToXMLMenuItem;
    private javax.swing.JMenu fileMenu;
    private javax.swing.JScrollPane jScrollPane1;
    private javax.swing.JMenuBar menuBar;
    private javax.swing.JSeparator menuSeparator1;
    private javax.swing.JSeparator menuSeparator2;
    private javax.swing.JSeparator menuSeparator3;
    private javax.swing.JMenuItem newMenuItem;
    private javax.swing.JMenuItem openMenuItem;
    private javax.swing.JMenuItem printMenuItem;
    private javax.swing.JMenuItem printSetupMenuItem;
    private javax.swing.JMenuItem samplesMenuItem;
    private javax.swing.JScrollPane samplesPanelScroll;
    private javax.swing.JTable samplesTable;
    private javax.swing.JMenuItem saveMenuItem;
    private javax.swing.JSeparator separator2;
    private javax.swing.JMenuItem setupDeviceMenuItem;
    private javax.swing.JMenuItem setupMenuItem;
    private javax.swing.JSplitPane splitPane;
    private javax.swing.JSplitPane splitPane2;
    private javax.swing.JLabel statusLabel;
    private javax.swing.JPanel statusPanel;
    private javax.swing.JTable tagsTable;
    private javax.swing.JMenuItem traceMenuItem;
    private javax.swing.JPanel traceTab;
    private javax.swing.JScrollPane traceTagsPanelScroll;
    // End of variables declaration//GEN-END:variables

    
    private void saveFile(FileHandler fileHandler, FileFilterImpl fileFilter)
    {
        if (getCurrentDevices().length > 0)
        {
            int retValue = -1;
            boolean go = false;
            File file = null;

            fileChooser.setFileFilter(fileFilter);

            do
            {
                fileChooser.setSelectedFile(new File(fileFilter.getExtension()));
                retValue = fileChooser.showSaveDialog(this);

                if(retValue != JFileChooser.APPROVE_OPTION)
                {
                    go = true;
                }
                else
                {
                    file = fileChooser.getSelectedFile();
                    if(file.getName().endsWith(fileFilter.getExtension()))
                    {
                        if(!file.exists())
                        {
                            go = true;
                        }
                        else
                        {
                            int option = JOptionPane.showConfirmDialog(this,
                                java.util.ResourceBundle.getBundle("properties/language").getString("thermologic.savefile.replaceMessage"),
                                String.format(
                                java.util.ResourceBundle.getBundle("properties/language").getString("thermologic.menu.fileSave"),
                                file.getName()),
                                JOptionPane.YES_NO_OPTION);

                            if(option == JOptionPane.YES_OPTION)
                            {
                                go= true;
                            }
                        }
                    }
                    else
                    {
                        JOptionPane.showMessageDialog(
                            this,
                            java.util.ResourceBundle.getBundle("properties/language").getString("thermologic.savefile.error1"),
                            String.format(
                            java.util.ResourceBundle.getBundle("properties/language").getString("thermologic.savefile.error"),
                            file.getName()),
                            JOptionPane.WARNING_MESSAGE);
                    }
                }
            }
            while(!go);


            if (retValue == JFileChooser.APPROVE_OPTION) {

                try {
                    fileHandler.save(file, getCurrentDevices());
                }
                catch (Exception e) {
                    e.printStackTrace(System.err);
                    logger.error(e);

                    JOptionPane.showMessageDialog(
                            this,
                            e.getLocalizedMessage(),
                            String.format(
                            java.util.ResourceBundle.getBundle("properties/language").getString("thermologic.savefile.error"),
                            file.getName()),
                            JOptionPane.ERROR_MESSAGE);
                }
            }
        }
    }
    
    private void initModels() {
        traceDataModel = new TraceDataModel();
        samplesDataModel = new SamplesDataModel();
        channelListModel = new ChannelListModel();
        configDataModel = new ConfigurationDataModel();
    }

    private void initCustomComponents() {
        
        adapter = AdapterFactory.getAdapter();        
        
        setupDialog = new SetupDialog(this);                
        adapter.addListener(this);

        fileChooser = new JFileChooser();
        fileChooser.setAcceptAllFileFilterUsed(false);
        fileChooser.setFileFilter(new FileFilterImpl());
        
        XMLFileChooser = new JFileChooser();
        XMLFileChooser.setAcceptAllFileFilterUsed(false);
        XMLFileChooser.setFileFilter(
                new FileFilterImpl(FileFilterImpl.EXCEL_EXTENSION)
                );

        root = new DefaultMutableTreeNode();
        deviceModel = new DefaultTreeModel(root);
        deviceTree.setModel(deviceModel);
        
        mainChart = new MainChart();
        splitPane.setBottomComponent(mainChart);
    }

    private void showPopup(MouseEvent evt) {
        
        if(evt.isPopupTrigger())
        {
            DefaultMutableTreeNode node = (DefaultMutableTreeNode)deviceTree.
                    getLastSelectedPathComponent();

            if (node != null)
            {
                Datalogger datalogger = (Datalogger) node.getUserObject();
                if(datalogger != null)
                {
                    devicePopupMenu.show(
                            evt.getComponent(), evt.getX(), evt.getY()
                            );
                }
            }
        }
    }
    
    private Device[] getCurrentDevices()
    {
        int count = root.getChildCount();
        Device[] devices = new Device[count];
        DefaultMutableTreeNode node = null;
        
        
        for(int i=0; i < count; i++)
        {
            node = (DefaultMutableTreeNode)root.getChildAt(i);
            Datalogger datalogger = (Datalogger)node.getUserObject();
            devices[i] = datalogger;
        }
        
        return devices;
    }

    @Override
    public void onEvent(AdapterEvent event)
    {
        statusLabel.setText(event.getEventMessage());
        
        /*
         * Warning: dependence on specific one wire event code 
         * @TODO: correct this
         */
        if(event.getEventCode().equals(EventCode.BEGIN.getCode()))
        {
            activityBar.setIndeterminate(true);
        }
        else if(event.getEventCode().equals(EventCode.END.getCode()))
        {
            /*
             * Fills the device tree
             */            
            populateDeviceTree(event.getAdapter().getDevices());
            
            activityBar.setIndeterminate(false);
        }
    }

    @Override
    public void onError(AdapterException ae)
    {
        JOptionPane.showMessageDialog(
                this, ae.getMessage(), this.getTitle(), JOptionPane.ERROR_MESSAGE
                );
    }
}
